home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / LIB / PANNER.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  16.4 KB  |  525 lines

  1.  
  2. package sub_arctic.lib;
  3.  
  4. import sub_arctic.input.*;
  5. import sub_arctic.output.*;
  6. import sub_arctic.constraints.std_function;
  7.  
  8. /**
  9.  * Class to allow a subtree to be scrolled in both x and y (i.e., "panned" 
  10.  * over).<p>
  11.  *
  12.  * Panner works as a composite object.  This is the tree built by the panner.<p>
  13.  *
  14.  *<pre>
  15.  *                         0
  16.  *                        / \
  17.  *                       /   \
  18.  *                      1     5
  19.  *                     / \
  20.  *                    /   \
  21.  *                   3     2
  22.  *                         |
  23.  *                         4
  24.  *</pre>
  25.  *
  26.  * Object above are inserted into parents in ascending order (not left to 
  27.  * right in the diagram).<p>
  28.  *
  29.  * #3 & #5 are only visible when necessary by the sizing.  
  30.  * (these used to be actually removed, we now just change their visibility).<p>
  31.  * 
  32.  * #2 and #3 are in that order due to the trickiness with FILL
  33.  * requiring a prev sibling -> next sibling FILL (this is not required with the
  34.  * new constraint system, but we don't fix what ain't broke...). <p>
  35.  *          
  36.  * 0 panner  no size, you set the size and position.  This exports the 
  37.  *                setting of the horizontal scrollbar as part_a and the 
  38.  *                vertical as part_b.<p>
  39.  * 1 parent_with_parts (x=0, y=0, h=MINUS_OFFSET(PARENT.RIGHT), 
  40.  *                w=FILL(PREVIOUS_SIBLING.LEFT)
  41.  *                This is child(0) of the panner and is constrained to 
  42.  *                transmits the setting of the horizontal scrollbar up as
  43.  *                its part_a.<p>
  44.  *
  45.  * 2 panner_helper (x=0, y=0, fits around child exactly.<p>
  46.  *
  47.  * 3 h_scrollbar (x=0, y=FAR_EDGE_JUST(PARENT.BOTTOM), 
  48.  *             w=MINUS_OFFSET(PARENT.RIGHT)<p>
  49.  *                
  50.  * 4 your interactor<p>
  51.  * 5 v_scrollbar x=FAR_EDGE_JUST(PREV_SIBLING.RIGHT), y=0, 
  52.  *            h=PLUS_OFFSET(PARENT.BOTTOM). 
  53.  *            This is child(1) of the panner.<p>
  54.  * 
  55.  * Note that from the panner child(0).child(0).child(0) is the
  56.  * object being panned.  From the outside, this can be more easily accessed
  57.  * as panned_child().<p>
  58.  *
  59.  * @Author Ian Smith
  60.  */
  61. public class panner extends parent_with_parts implements callback_object{
  62.  
  63.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  64.  
  65.   /** 
  66.    * The object being panned.
  67.    * @return interactor the single child of this object (which roots the 
  68.    *                    subtree being panned).
  69.    */
  70.   public interactor panned_child() { 
  71.     return child(0).child(0).child(0);
  72.   }
  73.  
  74.   /** 
  75.    * Set the object being panned.
  76.    * @param interactor c The single child of this object (which roots the 
  77.    *                     subtree being panned).
  78.    */
  79.   public void set_panned_child(interactor c) { 
  80.     /* reset to zero position*/
  81.     panner_helper ph=(panner_helper)(child(0).child(0));
  82.     ph.set_x(0);
  83.     ph.set_y(0);
  84.     
  85.     /* tell the panner helper what we have done */
  86.     if (ph.num_children()==0) {
  87.       ph.add_child(c);
  88.     } else {
  89.       ph.set_child(0,c);
  90.     }
  91.   }
  92.  
  93.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  94.  
  95.   /** Do we have a visible horizontal scrollbar. */
  96.   protected boolean have_h_slider;
  97.  
  98.   /** Do we have a visible vertical scrollbar. */
  99.   protected boolean have_v_slider;
  100.  
  101.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  102.  
  103.   /** Actual width of the object being panned. */
  104.   protected int _actual_width;
  105.  
  106.   /** Actual height of the object being panned. */
  107.   protected int _actual_height;
  108.  
  109.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  110.  
  111.   /** Our horizontal scrollbar. */
  112.   h_scrollbar h_control_slider;
  113.  
  114.   /** Our vertical scrollbar. */
  115.   v_scrollbar v_control_slider;
  116.  
  117.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  118.  
  119.   /** Variable to keep track of whether or not to force scrollbars.*/
  120.   protected boolean _force_scrollbars;
  121.  
  122.   /** 
  123.    * Indicate whether we are forcing  scrollbars to appear. 
  124.    * @return boolean indicating whether we force scrollbars to appear.
  125.    */
  126.   public boolean force_scrollbars() { return _force_scrollbars;};
  127.  
  128.   /** 
  129.    * Set whether we are forcing  scrollbars to appear. 
  130.    * @param boolean b indicating whether we force scrollbars to appear.
  131.    */
  132.   public void set_force_scrollbars(boolean b) { _force_scrollbars=b;};
  133.  
  134.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  135.  
  136.   /**
  137.    * This is where we do the magic with scrollbars (deciding visibility, etc.).
  138.    * @param int w new width of panned object.
  139.    * @param int h new height of panned object.
  140.    */
  141.   protected void new_child_size(int w, int h)  {
  142.     base_parent_interactor bpi=(base_parent_interactor)child(0).child(0);
  143.  
  144.     /* copy these in */
  145.     _actual_height=h;
  146.     _actual_width=w;
  147.  
  148.     /* take care of the force scrollbars */
  149.     if (_force_scrollbars) {
  150.       add_v_slider();
  151.       add_h_slider();
  152.       set_sbar_values();
  153.       return;
  154.     }
  155.  
  156.     /* ok, lets get rid of the simple case */
  157.     if ((_actual_height<=h()) && (_actual_width<=w())) {
  158.  
  159.       /* we know we don't need EITHER scrollbar */
  160.       /* if we have either of them, remove it */
  161.       if (have_h_slider) {
  162.     h_control_slider.set_visible(false);
  163.     h_control_slider.set_value(0);
  164.     have_h_slider=false;
  165.     bpi.set_x(0);
  166.       }
  167.  
  168.       if (have_v_slider) {
  169.     v_control_slider.set_visible(false);
  170.     v_control_slider.set_value(0);
  171.     have_v_slider=false;
  172.     bpi.set_y(0);
  173.       }
  174.  
  175.       return;
  176.     }
  177.  
  178.     /* do we need v scrollbar? There are two reasons we might:
  179.        1) _actual_height > h() 
  180.        2) _actual_width > w() &&
  181.           (_actual_height +  _h_control_slider.h()) > h() */
  182.  
  183.     /* lets do the simple case first */
  184.     if (_actual_height > h()) {
  185.       /* we are now needing to add one ... assuming we don't have 
  186.        one already */
  187.       if (have_v_slider==false) {
  188.     add_v_slider();
  189.       }
  190.     } else {
  191.       /* this is the *easy* removal case ... if it turns out we
  192.      are going to need this scrollbar for the complex reason
  193.      below, we end up adding it back... not very great, but
  194.      it will work */
  195.       if (have_v_slider==true) {
  196.     /* remove the sucker */
  197.     v_control_slider.set_visible(false);
  198.     v_control_slider.set_value(0);
  199.     have_v_slider=false;
  200.     bpi.set_y(0);
  201.       }
  202.     }
  203.  
  204.     /* do we need an h scrollbar in the simple case? */
  205.     if (_actual_width > w()) {
  206.       /* do we already have an sbar */
  207.       if (have_h_slider==false) {
  208.     add_h_slider();
  209.       }
  210.     } else {
  211.       /* again, this is the simple removal case... we may end up
  212.       adding it back again later */
  213.       if (have_h_slider==true) {
  214.     h_control_slider.set_visible(false);
  215.     h_control_slider.set_value(0);
  216.     have_h_slider=false;
  217.     bpi.set_x(0);
  218.       }
  219.     }
  220.  
  221.     /* at this point we know somebody has to need a scrollbar, 
  222.        and we also know that the simple removal cases are covered, so 
  223.        at least one of have_h_slider & have_v_slider is true ... 
  224.        in either case if the other one is false, we need to check 
  225.        for the complex case and add a scrollbar if necessary */
  226.     if ((have_h_slider==true) && (have_v_slider==false)) {
  227.       if (_actual_height + h_control_slider.h() > h()) {
  228.     /* need to add it any way */
  229.     add_v_slider();
  230.       }
  231.     }
  232.  
  233.     /* this is the other complex case */
  234.     if ((have_v_slider==true) && (have_h_slider==false)) {
  235.       if (_actual_width + v_control_slider.w() > w()) {
  236.     /* add it due to complex case */
  237.     add_h_slider();
  238.       }
  239.     }
  240.  
  241.     /* now set values */
  242.     set_sbar_values();
  243.   }
  244.  
  245.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  246.  
  247.   /** 
  248.    * This code makes the horizontal slider visible. It doesn't try to
  249.    * put in the right maximum value, this is done in set_sbar_values(). 
  250.    */
  251.   protected void add_h_slider()  { 
  252.  
  253.     /* make it visible */
  254.     have_h_slider=true;
  255.     h_control_slider.set_visible(true);
  256.     h_control_slider.set_value(0);
  257.   }
  258.  
  259.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  260.  
  261.   /**
  262.    * This code make the horizontal slider visible. It doesn't try to
  263.    * put in the right maximum value, this is done in set_sbar_values(). 
  264.    */
  265.   protected void add_v_slider()   {
  266.  
  267.     /* make it visible and reset its value */
  268.     have_v_slider=true;
  269.     v_control_slider.set_visible(true);
  270.     v_control_slider.set_value(0);
  271.   }
  272.  
  273.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  274.  
  275.   /** This sets the scrollbar values such as max value. */
  276.   protected void set_sbar_values() {
  277.     
  278.     /* set the values ... vertical first*/
  279.     if (have_v_slider) {
  280.  
  281.       /* if we have an h slider compensate */
  282.       if (have_h_slider) {
  283.     v_control_slider.set_max_val(_actual_height-
  284.                      (h()-(h_control_slider.h())));
  285.     v_control_slider.
  286.       set_thumb_percentage(((double)h()-(double)h_control_slider.h())/
  287.                    ((double)_actual_height));
  288.       } else {
  289.     /* simple case, just figure out how much of a pan we need */
  290.     v_control_slider.set_max_val(_actual_height-h());
  291.     v_control_slider.
  292.       set_thumb_percentage(((double)h())/((double)_actual_height));
  293.       }
  294.       // set increments to be a little less than a screenfull
  295.       v_control_slider.set_large_inc(h()-v_control_slider.small_inc());
  296.     }
  297.  
  298.     /* now set the horiz value */
  299.     if (have_h_slider) {
  300.       /* compensate for possible v slider */
  301.       if (have_v_slider) {
  302.  
  303.     h_control_slider.set_max_val(_actual_width-
  304.                      (w()-(v_control_slider.w())));
  305.     h_control_slider.
  306.       set_thumb_percentage(((double)w()-(double)v_control_slider.w())/
  307.                    ((double)_actual_width));
  308.       } else {
  309.  
  310.     /* simple case horizontally */
  311.     h_control_slider.set_max_val(_actual_width-w());
  312.     h_control_slider.
  313.       set_thumb_percentage(((double)w())/((double)_actual_width));
  314.       }
  315.       // set increments to be a little less than a screenfull
  316.       h_control_slider.set_large_inc(w()-h_control_slider.small_inc());
  317.     }
  318.   }
  319.  
  320.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  321.  
  322.   /** 
  323.    * Handle the fact that child's size changed in y. 
  324.    * @param int newvalue new size value.
  325.    */
  326.   protected void child_size_changed_h(int newvalue) {
  327.     new_child_size(panned_child().w(),newvalue);
  328.   }
  329.  
  330.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  331.  
  332.   /**
  333.    * Handle the fact that child's size changed in x. 
  334.    * @param int newvalue new size value.
  335.    */
  336.   protected void child_size_changed_w(int newvalue) {
  337.     new_child_size(newvalue,panned_child().h());
  338.   }
  339.  
  340.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  341.  
  342.   /**
  343.    * Create a new panner which pans over the given child. 
  344.    * We assume you will set the w, h, and x,y with constraints.
  345.    *
  346.    * @param base_interactor chld the root of the subtree we are panning over.
  347.    */
  348.   public panner(base_interactor chld)  {
  349.     super(0,0);
  350.  
  351.     parent_with_parts bpi;
  352.     panner_helper ph;
  353.  
  354.     /* put the parent and panner_helper */
  355.     bpi=new parent_with_parts(0,0);
  356.     bpi.set_h_constraint(std_function.offset(PARENT.Y2(), 0));
  357.     bpi.set_w_constraint(std_function.fill(PREV_SIBLING.X(), NEXT_SIBLING.X(), 0));
  358.     add_child(bpi);
  359.  
  360.     ph=new panner_helper();
  361.     ph.set_x(0);
  362.     ph.set_y(0);
  363.     ph.set_w_constraint(std_function.offset(FIRST_CHILD.X2(),0));
  364.     ph.set_h_constraint(std_function.offset(FIRST_CHILD.Y2(),0));
  365.     bpi.add_child(ph);
  366.  
  367.     /* put the scrollbars in place */
  368.     h_control_slider=new h_scrollbar(this);
  369.     h_control_slider.set_x(0);
  370.     h_control_slider.set_y_constraint(std_function.far_edge_just(PARENT.Y2(),0));
  371.     h_control_slider. set_w_constraint(std_function.offset(PARENT.X2(),0));
  372.     child(0).set_child(1,h_control_slider);
  373.  
  374.     v_control_slider=new v_scrollbar(this);
  375.     v_control_slider.set_x_constraint(std_function.far_edge_just(PARENT.X2(), 0));
  376.     v_control_slider.set_y(0);
  377.     v_control_slider.set_h_constraint(std_function.offset(PARENT.Y2(), 0));
  378.     set_child(1,v_control_slider);
  379.  
  380.     // set increments to be a little less than a screenfull
  381.     h_control_slider.set_large_inc(w()-h_control_slider.small_inc());
  382.     v_control_slider.set_large_inc(h()-v_control_slider.small_inc());
  383.  
  384.     /* initially we don't have visible scrollbars */
  385.     have_h_slider=have_v_slider=false;
  386.     h_control_slider.set_visible(false);
  387.     v_control_slider.set_visible(false);
  388.  
  389.     /* set constraints to copy out the settings of the scrollbars */
  390.     bpi.set_part_a_constraint(std_function.eq(LAST_CHILD.PART_A()));
  391.     set_part_a_constraint(std_function.eq(FIRST_CHILD.PART_A()));
  392.     set_part_b_constraint(std_function.eq(LAST_CHILD.PART_A()));
  393.  
  394.     /* setup things for this new panned child */
  395.     set_panned_child(chld);
  396.   }
  397.  
  398.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  399.  
  400.   /** 
  401.    * Callback routine that receives callbacks from the scrollbars. 
  402.    * 
  403.    * @param interactor from_obj      the interactor the callback is from.
  404.    * @param event      evt           the event "causing" the callback.
  405.    * @param int        callback_num  the number of the callback (indicating 
  406.    *                                 what kind).
  407.    * @param Object     callback_info parameter information associated with the 
  408.    *                                 callback.
  409.    */
  410.   public void callback(interactor       from_obj, 
  411.                event            evt,
  412.                int              callback_num, 
  413.                Object           callback_info)
  414.   {
  415.     Integer value=(Integer)callback_info;
  416.     int v=value.intValue();
  417.     base_parent_interactor bpi;
  418.  
  419.     /* we don't want anything except real time! ignore static callback */
  420.     if (callback_num == h_slider.STATIC_CALLBACK) return;
  421.  
  422.     /* get the object we move around */
  423.     bpi=(base_parent_interactor)child(0).child(0);
  424.  
  425.     /* horizontal move */
  426.     if (from_obj == h_control_slider) {
  427.       bpi.set_x(-v);
  428.     } else {
  429.       /* vertical move */
  430.       bpi.set_y(-v);
  431.     }
  432.   }
  433.  
  434.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  435.  
  436.   /** 
  437.    * Catch our resizes so we can change scrollbars, etc. 
  438.    * @param int v new h value.
  439.    */
  440.   protected void set_raw_h(int v)  {
  441.     super.set_raw_h(v);
  442.     /* recompute the values for sbars and whatnot*/
  443.     new_child_size(panned_child().w(), panned_child().h());
  444.   }
  445.  
  446.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  447.  
  448.   /** 
  449.    * Catch our resizes so we can change scrollbars, etc. 
  450.    * @param int v new w value.
  451.    */
  452.   protected void set_raw_w(int v)  {
  453.     super.set_raw_w(v);
  454.     /* recompute the values for sbars and whatnot*/
  455.     new_child_size(panned_child().w(), panned_child().h());
  456.   }
  457.  
  458.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  459.   /**
  460.    * This function is used to control X coordinate of the point which
  461.    * the upper left corner of the panner is viewing.
  462.    * @param int x the x coordinate of the top left corner of the panner 
  463.    *              with respect to the panned object
  464.    */
  465.   public void set_x_view_coordinate(int x) {
  466.     base_parent_interactor bpi;
  467.  
  468.     bpi=(base_parent_interactor)child(0).child(0);
  469.  
  470.     /* validity check */
  471.     if (x<h_control_slider.min_val()) {
  472.       x=h_control_slider.min_val();
  473.     }
  474.     if (x>h_control_slider.max_val()) {
  475.       x=h_control_slider.max_val();
  476.     }
  477.     /* its in the range, just set the slider */
  478.     h_control_slider.set_value(x);
  479.     /* move the panner's display */
  480.  
  481.     bpi.set_x(-x);
  482.   }
  483.   /**
  484.    * This function is used to control Y coordinate of the point which
  485.    * the upper left corner of the panner is viewing.
  486.    * @param int y the y coordinate of the top left corner of the panner 
  487.    *              with respect to the panned object
  488.    */
  489.   public void set_y_view_coordinate(int y) {
  490.     base_parent_interactor bpi;
  491.  
  492.     bpi=(base_parent_interactor)child(0).child(0);
  493.  
  494.     /* validity check */
  495.     if (y<v_control_slider.min_val()) {
  496.       y=v_control_slider.min_val();
  497.     }
  498.     if (y>v_control_slider.max_val()) {
  499.       y=v_control_slider.max_val();
  500.     }
  501.     /* its in the range, just set the slider */
  502.     v_control_slider.set_value(y);
  503.     /* move the panner's display */
  504.  
  505.     bpi.set_y(-y);
  506.   }
  507. }
  508.  
  509. /*=========================== COPYRIGHT NOTICE ===========================
  510.  
  511. This file is part of the subArctic user interface toolkit.
  512.  
  513. Copyright (c) 1996 Scott Hudson and Ian Smith
  514. All rights reserved.
  515.  
  516. The subArctic system is freely available for most uses under the terms
  517. and conditions described in 
  518.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  519. and appearing in full in the lib/interactor.java source file.
  520.  
  521. The current release and additional information about this software can be 
  522. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  523.  
  524. ========================================================================*/
  525.